
package com.sausageking.shared;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.common.base.Strings;

public abstract class BaseUtil {

  enum Environment {
    TEST, PROD
  }

  private static final Environment env
  // = Environment.TEST;
  = Environment.PROD;

  private static final String FB_GRAPH_URL = "https://graph.facebook.com/";

  private static final String FB_OAUTH_URL = FB_GRAPH_URL + "oauth/";

  private static final String FB_FRIENDS_URL = FB_GRAPH_URL + "me/friends?";

  private static final String FB_ME_URL = FB_GRAPH_URL + "me?";

  private String getAppId() {
    return env.equals(Environment.TEST) ? "291222254222537" : "126613800776470";
  }

  private String getAppSecret() {
    return env.equals(Environment.TEST)
        ? "7bce2f52ec15561c77c4661595dfe7b7"
        : "8f011651b69d78667c6cda572929c8c7";
  }

  private String getAuthRedirectUrl() {
    return env.equals(Environment.TEST)
        ? "http://localhost:8888/facebook/auth/"
        : "http://www.offersticker.com/facebook/auth/";
  }

  public String getFullMerchantUrl(String merchantId) {
    String page = "mobile.html";
    return env.equals(Environment.TEST) ? "http://localhost:8888/?page=" + page
        + "#deal:merchant_" + merchantId : "http://www.offersticker.com/?page="
        + page + "#deal:merchant_" + merchantId;
  }

  public String getShortMerchantUrl(String merchantId) {
    return env.equals(Environment.TEST)
        ? "http://localhost:8888/" + merchantId
        : "http://1800.bz/" + merchantId;
  }

  public String getShortMerchantUrlNoProtocol(String merchantId) {
    return env.equals(Environment.TEST)
        ? "localhost:8888/" + merchantId
        : "1800.bz/" + merchantId;
  }

  public String getFacebookAuthorizeUrl(String page, String place, String token) {
    final StringBuilder sb = new StringBuilder(FB_OAUTH_URL);
    sb.append("authorize?client_id=").append(getAppId());
    sb.append("&redirect_uri=").append(getAuthServletUrl(page, place, token));
    // sb.append("&scope=publish_stream,offline_access");
    sb.append("&scope=publish_stream,email");
    sb.append("&display=touch");
    return sb.toString();
  }

  public String getFacebookAccessTokenUrl(final String authToken, String page,
      String place, String token) {
    final StringBuilder sb = new StringBuilder(FB_OAUTH_URL);
    sb.append("access_token?canvas=1&fbconnect=0&type=user_agent&client_id=")
        .append(getAppId());
    sb.append("&redirect_uri=").append(getAuthServletUrl(page, place, token));
    sb.append("&client_secret=").append(getAppSecret());
    sb.append("&code=").append(authToken);
    return sb.toString();
  }

  public String getFacebookFriendsUrl(final String authToken) {
    return FB_FRIENDS_URL + authToken;
  }

  public String getFacebookUserUrl(String accessToken) {
    return FB_ME_URL + accessToken;
  }

  public String getProfilePictureUrl(String userId) {
    return FB_GRAPH_URL + userId + "/picture?type=large";
  }

  private String getAuthServletUrl(String page, String place, String token) {
    if (Strings.isNullOrEmpty(page)) {
      page = "consumer.html";
    }
    if (Strings.isNullOrEmpty(place)) {
      place = "pl";
    }
    if (Strings.isNullOrEmpty(token)) {
      token = "undefined";
    }
    String authServlet = encode(new StringBuilder()
        .append(getAuthRedirectUrl()).append("?page=").append(page)
        .append("&place=").append(place).append("&token=").append(token)
        .toString());

    return authServlet;
  }

  public String getIconUrl() {
    return "http://www.offersticker.com/resources/icon.png";
  }

  public String stripParam(String key, String token) {
    Map<String, List<String>> params = getParametersFromToken(token);
    params.remove(key);
    return getTokenFromParameters(params);
  }

  private Map<String, List<String>> getParametersFromToken(String token) {
    Map<String, List<String>> params = new HashMap<String, List<String>>();
    if (token == null || token.isEmpty()) {
      return params;
    }
    try {
      token = decode(token);
    } catch (Exception e) {
      // ignore
    }
    for (String param : token.split("__")) { // equivalence of "&"
      String pair[] = param.split("_"); // equivalence of "="
      String key = pair[0];
      String value = pair[1];
      List<String> values = params.get(key);
      if (values == null) {
        values = new ArrayList<String>();
        params.put(key, values);
      }
      values.add(value);
    }
    return params;
  }

  private String getTokenFromParameters(Map<String, List<String>> params) {
    StringBuilder builder = new StringBuilder();
    for (String key : params.keySet()) {
      builder.append(key + "_" + params.get(key).get(0) + "__");
    }

    String token = builder.toString();
    if (token.contains("__")) {
      token = token.substring(0, token.length() - 2);
    }
    return token;
  }

  public String getParameterFromToken(String key, String token) {
    Map<String, List<String>> tokenParamMap = getParametersFromToken(token);
    List<String> values = tokenParamMap.get(key);
    if (values != null && !values.isEmpty()) {
      return values.get(0);
    } else {
      return null;
    }
  }

  public String addParamToToken(String token, String key, String value) {
    return token + "__" + key + "_" + value;
  }

  public long getRedemptionExpirationInMs() {
    // return env.equals(Environment.TEST) ? 10 * 1000 // 20s
    // : 60 * 60 * 1000; // 1h
    return env.equals(Environment.TEST) ? 10 * 1000 : 10 * 1000;
  }

  public long getMinStampIntervalInMs() {
    // Note check for stamp-too-soon is actually done at server side
    return env.equals(Environment.TEST) ? 600 * 1000
        : 600 * 1000;
  }

  public boolean isTestAccount(String email) {
    return email.endsWith("@1800.bz");
  }
  
  abstract public void redirect(String url);

  abstract public String encode(String string);

  abstract public String decode(String string);
}